package com.xique.common.core.utils;

import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClient;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.model.OSSObject;
import com.aliyun.oss.model.ObjectMetadata;
import com.xique.common.core.constant.OssFilePrefixConstants;
import com.xique.common.core.enums.StatusCode;
import com.xique.common.core.web.domain.AjaxResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URL;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * Created by IntelliJ IDEA. 阿里oss工具类
 *
 * @author Administrator description: path: platform-com.jzy.oms.util-AliossUtil date: 2020/8/29
 * 11:14
 */
@Component
public class AliossUtil {
    private static final String[] IMAGE_TYPE = new String[]{".bmp", ".jpg", ".jpeg", ".gif", ".png"};
    private static final String[] VIDEO_TYPE =
            new String[]{".AVI", ".mov", ".rmvb", ".rm", ".FLV", ".mp4", ".3GP"};
    private static final String[] PACKAGE_TYPE = new String[]{".bin"};

    private static final Logger logger = LoggerFactory.getLogger(AliossUtil.class);

    @Value("${alioss.endpoint}")
    private String endPoint;

    @Value("${alioss.accessKeyId}")
    private String accessKeyId;

    @Value("${alioss.accessKeySecret}")
    private String accessKeySecret;

    @Value("${alioss.park.bucketName}")
    private String bucketName;

    @Value("${alioss.park.filehost}")
    private String fileHost;

    @Value("${aliossPark.endpoint}")
    private String endPointPark;

    @Value("${aliossPark.accessKeyId}")
    private String accessKeyIdPark;

    @Value("${aliossPark.accessKeySecret}")
    private String accessKeySecretPark;

    @Value("${aliossPark.bucketName}")
    private String bucketNamePark;

    @Value("${alioss.jzy.endpoint}")
    private String jzyEndPoint;

    @Value("${alioss.jzy.accessKeyId}")
    private String jzyAccessKeyId;

    @Value("${alioss.jzy.accessKeySecret}")
    private String jzyAccessKeySecret;

    @Value("${alioss.jzy.bucketName}")
    private String jzyParkBucketName;

    public Map<String, Object> uploadFile(MultipartFile uploadFile, String prefix) {
        Map<String, Object> returnMap = new HashMap<>();
        // 返回图片上传后返回的url
        String returnImgeUrl = "";
        // 校验图片格式
        boolean isLegal = false;
        ObjectMetadata meta = new ObjectMetadata();
        if (Arrays.asList(
                        OssFilePrefixConstants.LOGIN_PAGE,
                        OssFilePrefixConstants.DOOR_ADVERT_IMGAGE,
                        OssFilePrefixConstants.FACE_URL,
                        OssFilePrefixConstants.MINI_IMGAGE,
                        OssFilePrefixConstants.OPERATE_IMGAGE)
                .contains(prefix)) {
            meta.setContentType("image/jpg");
            for (String type : IMAGE_TYPE) {
                if (StringUtils.endsWithIgnoreCase(uploadFile.getOriginalFilename(), type)) {
                    isLegal = true;
                    break;
                }
            }
        } else if (Arrays.asList(
                        OssFilePrefixConstants.DOOR_ADVERT_VIDEO, OssFilePrefixConstants.OPERATE_VIDEO)
                .contains(prefix)) {
            meta.setContentType("video/mp4");
            for (String type : VIDEO_TYPE) {
                if (StringUtils.endsWithIgnoreCase(uploadFile.getOriginalFilename(), type)) {
                    isLegal = true;
                    break;
                }
            }
        } else if (Arrays.asList(OssFilePrefixConstants.INSTALLATION_PACKAGE).contains(prefix)) {
            meta.setContentType("bin");
            for (String type : PACKAGE_TYPE) {
                if (StringUtils.endsWithIgnoreCase(uploadFile.getOriginalFilename(), type)) {
                    isLegal = true;
                    break;
                }
            }
        }
        // 如果格式不合法
        if (!isLegal) {
            returnMap.put("code", StatusCode.ERROR.getCode());
            return returnMap;
        }
        // 获取文件原名称
        String originalFilename = uploadFile.getOriginalFilename();
        // 获取文件类型
        String fileType = originalFilename.substring(originalFilename.lastIndexOf("."));
        // 新文件名称
        String newFileName = UUID.randomUUID().toString() + fileType;
        // 构建日期路径, 例如：OSS目标文件夹/2020/10/31/文件名
        String filePath = new SimpleDateFormat("yyyy/MM/dd").format(new Date());
        // 文件上传的路径地址
        String uploadImgeUrl = prefix + "/" + filePath + "/" + newFileName;

        // 获取文件输入流
        InputStream inputStream = null;
        try {
            inputStream = uploadFile.getInputStream();
        } catch (IOException e) {
            e.printStackTrace();
        }

        // 文件上传至阿里云OSS
        OSSClient ossClient = new OSSClient(endPoint, accessKeyId, accessKeySecret);
        ossClient.putObject(bucketName, uploadImgeUrl, inputStream, meta);

        // 获取文件上传后的图片返回地址
        returnImgeUrl = "http://" + bucketName + "." + endPoint + "/" + uploadImgeUrl;
        logger.info("固定路径:" + returnImgeUrl);

        returnMap.put("code", StatusCode.SUCCESS.getCode());
        returnMap.put("url", returnImgeUrl);
        returnMap.put("objectName", uploadImgeUrl);

        return returnMap;
    }

    public String download(String fileName, HttpServletResponse response)
            throws UnsupportedEncodingException {
        response.setHeader(
                "Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));

        OSSClient ossClient = new OSSClient(endPoint, accessKeyId, accessKeySecret);
        OSSObject ossObject = ossClient.getObject(bucketName, fileName);
        try {
            // 读取文件内容。
            InputStream inputStream = ossObject.getObjectContent();
            // 把输入流放入缓存流
            BufferedInputStream in = new BufferedInputStream(inputStream);
            ServletOutputStream outputStream = response.getOutputStream();
            // 把输出流放入缓存流
            BufferedOutputStream out = new BufferedOutputStream(outputStream);
            byte[] buffer = new byte[1024];
            int len = 0;
            while ((len = in.read(buffer)) != -1) {
                out.write(buffer, 0, len);
            }
            if (out != null) {
                out.flush();
                out.close();
            }
            if (in != null) {
                in.close();
            }
            return StatusCode.SUCCESS.getMsg();
        } catch (Exception e) {
            return StatusCode.ERROR.getMsg();
        }
    }

    public String delete(String fileName) {

        try {
            /** 注意：在实际项目中，不需要删除OSS文件服务器中的文件， 只需要删除数据库存储的文件路径即可！ */
            // 建议在方法中创建OSSClient 而不是使用@Bean注入，不然容易出现Connection pool shut down
            OSSClient ossClient = new OSSClient(endPoint, accessKeyId, accessKeySecret);
            // 根据BucketName,filetName删除文件
            // 删除目录中的文件，如果是最后一个文件fileoath目录会被删除。
            ossClient.deleteObject(bucketName, fileName);
            ossClient.shutdown();
            System.out.println("文件删除！");
            return StatusCode.SUCCESS.getMsg();
        } catch (Exception e) {
            e.printStackTrace();
            return StatusCode.ERROR.getMsg();
        }
    }

    /**
     * 人脸图片上传alioss
     *
     * @param byteArrayInputStream
     * @return
     */
    public Map<String, Object> uploadByByteArray(ByteArrayInputStream byteArrayInputStream) {
        // 新文件名称
        String newFileName = UUID.randomUUID().toString() + ".jpg";
        // 构建日期路径, 例如：OSS目标文件夹/2020/10/31/文件名
        String filePath = new SimpleDateFormat("yyyy/MM/dd").format(new Date());
        // 文件上传的路径地址
        String uploadImgeUrl = fileHost + "/" + filePath + "/" + newFileName;

        // 文件上传至阿里云OSS
        OSSClient ossClient = new OSSClient(endPoint, accessKeyId, accessKeySecret);
        ossClient.putObject(bucketName, uploadImgeUrl, byteArrayInputStream);
        ossClient.shutdown();

        // 获取文件上传后的图片返回地址
        String returnImgeUrl = "http://" + bucketName + "." + endPoint + "/" + uploadImgeUrl;
        logger.info("固定路径:" + returnImgeUrl);

        Map<String, Object> returnMap = new HashMap<>();
        returnMap.put("code", StatusCode.SUCCESS.getCode());
        returnMap.put("url", returnImgeUrl);
        returnMap.put("objectName", uploadImgeUrl);

        return returnMap;
    }

    /**
     * 压缩照片到指定大小，并上传到oss
     *
     * @param file
     * @return
     */
    public Map<String, Object> reduceImageSizeAndUpload(MultipartFile file, long fileSize) {
        Map<String, Object> returnMap = new HashMap<>();
        // 1、校验图片格式
        boolean isLegal = false;
        for (String type : IMAGE_TYPE) {
            if (StringUtils.endsWithIgnoreCase(file.getOriginalFilename(), type)) {
                isLegal = true;
                break;
            }
        }
        if (!isLegal) {
            returnMap.put("code", StatusCode.ERROR.getCode());
            return returnMap;
        }

        // 2、压缩图片并导入到oss
        byte[] bytes = new byte[0];
        try {
            bytes = PicUtil.commpressPicCycle(file.getBytes(), fileSize, 0.8);
        } catch (IOException e) {
            e.printStackTrace();
            return AjaxResult.error();
        }
        ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);
        Map<String, Object> upload = this.uploadByByteArray(byteArrayInputStream);
        return upload;
    }

    /**
     * 人脸图片上传alioss
     *
     * @param byteArrayInputStream
     * @return
     */
    public Map<String, Object> uploadByByteArrayV1(
            ByteArrayInputStream byteArrayInputStream, String fileType) {
        // 新文件名称
        String newFileName = UUID.randomUUID().toString() + ".jpg";
        // 构建日期路径, 例如：OSS目标文件夹/2020/10/31/文件名
        String filePath = new SimpleDateFormat("yyyy/MM/dd").format(new Date());
        // 文件上传的路径地址
        String uploadImgeUrl = fileType + "/" + filePath + "/" + newFileName;

        // 文件上传至阿里云OSS
        OSSClient ossClient = new OSSClient(endPoint, accessKeyId, accessKeySecret);
        ossClient.putObject(bucketName, uploadImgeUrl, byteArrayInputStream);
        ossClient.shutdown();

        // 获取文件上传后的图片返回地址
        String returnImgeUrl = "http://" + bucketName + "." + endPoint + "/" + uploadImgeUrl;
        logger.info("固定路径:" + returnImgeUrl);

        Map<String, Object> returnMap = new HashMap<>();
        returnMap.put("code", StatusCode.SUCCESS.getCode());
        returnMap.put("url", returnImgeUrl);
        returnMap.put("objectName", uploadImgeUrl);

        return returnMap;
    }

    /**
     * 压缩照片到指定大小，并上传到oss
     *
     * @param file
     * @return
     */
    public Map<String, Object> reduceImageSizeAndUploadV1(
            MultipartFile file, long fileSize, String fileType) {
        Map<String, Object> returnMap = new HashMap<>();
        // 1、校验图片格式
        boolean isLegal = false;
        for (String type : IMAGE_TYPE) {
            if (StringUtils.endsWithIgnoreCase(file.getOriginalFilename(), type)) {
                isLegal = true;
                break;
            }
        }
        if (!isLegal) {
            returnMap.put("code", StatusCode.ERROR.getCode());
            return returnMap;
        }

        // 2、压缩图片并导入到oss
        byte[] bytes = new byte[0];
        try {
            bytes = PicUtil.commpressPicCycle(file.getBytes(), fileSize, 0.9);
        } catch (IOException e) {
            e.printStackTrace();
            return AjaxResult.error();
        }
        ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);
        Map<String, Object> upload = this.uploadByByteArrayV1(byteArrayInputStream, fileType);
        return upload;
    }

    public URL getGetObjectUrl(String objectName) {
        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(endPoint, accessKeyId, accessKeySecret);
        // 设置URL过期时间为2分钟。
        Date expiration = new Date(System.currentTimeMillis() + 120 * 1000);
        // 生成以GET方法访问的签名URL，访客可以直接通过浏览器访问相关内容。
        URL url = ossClient.generatePresignedUrl(bucketName, objectName, expiration);
        System.out.println(url);
        // 关闭OSSClient。
        ossClient.shutdown();
        return url;
    }

    /**
     * @description: 上传全视通固件升级包
     * @author caogq
     * @date 2021/11/5 9:54
     * @version 1.0
     */
    public Map<String, Object> uploadFreeviewUpgradeFile(MultipartFile uploadFile) {
        Map<String, Object> returnMap = new HashMap<>();
        // 如果文件格式不合法
        if (!StringUtils.endsWithIgnoreCase(uploadFile.getOriginalFilename(), ".bin")) {
            returnMap.put("code", StatusCode.ERROR.getCode());
            return returnMap;
        }
        // 获取文件原名称
        String originalFilename = uploadFile.getOriginalFilename();

        // 构建日期路径, 例如：OSS目标文件夹/2020/10/31/文件名
        String filePath = new SimpleDateFormat("yyyy/MM/dd").format(new Date());
        // 文件上传的路径地址
        String uploadUrl = fileHost + "/" + filePath + "/" + originalFilename;

        // 获取文件输入流
        InputStream inputStream = null;
        try {
            inputStream = uploadFile.getInputStream();
        } catch (IOException e) {
            e.printStackTrace();
        }
        ObjectMetadata meta = new ObjectMetadata();
        // 文件上传至阿里云OSS
        OSSClient ossClient = new OSSClient(endPoint, accessKeyId, accessKeySecret);
        ossClient.putObject(bucketName, uploadUrl, inputStream, meta);

        // 获取文件上传后的图片返回地址
        String url = "https://" + bucketName + "." + endPoint + "/" + uploadUrl;
        logger.info("全视通固件包oss路径:" + url);
        returnMap.put("code", StatusCode.SUCCESS.getCode());
        returnMap.put("url", url);

        return returnMap;
    }

    public URL getGetObjectUrlPark(String objectName) {
        // 创建OSSClient实例。
        OSS ossClient =
                new OSSClientBuilder().build(endPointPark, accessKeyIdPark, accessKeySecretPark);
        // 设置URL过期时间为2分钟。
        Date expiration = new Date(System.currentTimeMillis() + 120 * 1000);
        // 生成以GET方法访问的签名URL，访客可以直接通过浏览器访问相关内容。
        URL url = ossClient.generatePresignedUrl(bucketNamePark, objectName, expiration);
        System.out.println(url);
        // 关闭OSSClient。
        ossClient.shutdown();
        return url;
    }

    /**
     * 根据ObjectName 获取图片访问路径
     *
     * @param objectName
     * @return
     */
    public URL getJzyGetObjectUrl(String objectName) {
        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(jzyEndPoint, jzyAccessKeyId, jzyAccessKeySecret);
        // 设置URL过期时间为2分钟。
        Date expiration = new Date(System.currentTimeMillis() + 120 * 1000);
        // 生成以GET方法访问的签名URL，访客可以直接通过浏览器访问相关内容。
        URL url = ossClient.generatePresignedUrl(jzyParkBucketName, objectName, expiration);
        System.out.println(url);
        // 关闭OSSClient。
        ossClient.shutdown();
        return url;
    }

    public URL getXylParkGetObjectUrl(String objectName) {
        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(jzyEndPoint, jzyAccessKeyId, jzyAccessKeySecret);
        // 设置URL过期时间为2分钟。
        Date expiration = new Date(System.currentTimeMillis() + 60 * 60 * 1000);
        // 生成以GET方法访问的签名URL，访客可以直接通过浏览器访问相关内容。
        URL url = ossClient.generatePresignedUrl(jzyParkBucketName, objectName, expiration);
        System.out.println(url);
        // 关闭OSSClient。
        ossClient.shutdown();
        return url;
    }

    public OSS getClient() {
        return new OSSClientBuilder().build(endPoint, accessKeyId, accessKeySecret);
    }

    public String uploadVendorPic(String base64) {
        // 使用插件传输产生的前缀
        String suffix = base64.substring(11,base64.indexOf(";"));
        String prefix = base64.substring(0,base64.indexOf(",") + 1);
        // 替换前缀为空
        base64 = base64.replace(prefix,"");
        byte[] decode = Base64.getDecoder().decode(base64);

        // 返回图片上传后返回的url
        String returnImgeUrl = "";
        // 新文件名称
        String newFileName = UUID.randomUUID() + "."+suffix;
        // 文件上传的路径地址
        String uploadImgeUrl = "icbc" + "/" + newFileName;


        // 文件上传至阿里云OSS
        OSSClient ossClient = new OSSClient(endPoint, accessKeyId, accessKeySecret);
        ossClient.putObject(bucketName, uploadImgeUrl, new ByteArrayInputStream(decode));

        // 获取文件上传后的图片返回地址
        returnImgeUrl = "http://" + bucketName + "." + endPoint + "/" + uploadImgeUrl;

        return returnImgeUrl;
    }
}
